home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file contains procedures connected with maintaining a list of
- * segments in use in the program.
- *
- * The following operations are defined:
- * LOOKUP MODULE
- * Returns head of segment list for named module.
- * For new module it inserts a new module name if there is room, otherwise the
- * result will be NULL.
- * DEFINE SEGMENT
- * Look up module name. If o.k. search for segment by number. If not found
- * attempt to insert a new segment into list. Store segment location and enter segment
- * into hash table.
- * MOVE SEGMENT
- * Look for segment in hash table. Remove old hash table entry, change position,
- * re-enter position in hash table.
- * DISCARD SEGMENT
- * Remove segment from hash table. Set location to 0.
- * FIND SEGMENT
- * Lookup segment in hash table. Returns pointer to entry.
- */
- #include <stdio.h>
- #include <process.h>
- #include <malloc.h>
- #include <dgb.h>
- #include <exc.h>
- #include "types.h"
- #include "profile.h"
- #include "segments.h"
- #include "trace.h"
- #include "symfile.h"
-
- #define NextHash(i) ((i) = ((i)+1)%MAXHASHVAL)
- PSEGMENT hashtable[MAXHASHVAL] = { UNUSED };
- MODULENAME modules[MAXMODULE];
- SEGMENT segs[MAXSEGMENT];
- PSEGMENT FreeSeg = &segs[0];
- PMODULE FreeMod = &modules[0];
-
- /* This procedure has to return a success code because I don't trust
- * the exception handling to work proerly when I'm in an interrupt
- * routine (SS != DS).
- */
- PMODULE LookupModule (m)
- LPSTR m;
- {
- PMODULE pm;
- LPSTR s, t;
- for (pm = &modules[0]; pm < FreeMod; pm++)
- {
- for (s = m, t = pm->name; *s == *t; s++, t++)
- {
- if (*t == 0) return pm;
- }
- }
- if (FreeMod < ARRAY_END(modules))
- {
- WORD i;
- s = m;
- for (i = 0; i <= 8; i++)
- {
- FreeMod->name[i] = *s++;
- }
- FreeMod->name[8] = 0;
- FreeMod->pseg = NULL;
- return FreeMod++;
- }
- return NULL;
- }
-
- PSEGMENT DefineSegment (ModName, Ordinal, SegLoc, Instance, Type)
- LPSTR ModName;
- WORD Ordinal, SegLoc, Instance, Type;
- {
- PSEGMENT ps = FindSegment (ModName, Ordinal, Instance, Type);
- if (ps == NULL) return NULL;
- HashRemove (ps);
- ps->location = SegLoc;
- HashInsert (ps);
- return ps;
- }
-
- void MoveSegment (from, to)
- WORD from, to;
- {
- PSEGMENT ps = HashFind (from);
- unless (ps == NULL)
- {
- HashRemove (ps);
- ps->location = to;
- unless (to == NULL) HashInsert(ps);
- /*trace("Moved %s@%d from %w to %w\n", (LPSTR) ps->module->name, ps->ordinal, from, to);*/
- }
- }
-
- void DiscardSegment (loc)
- WORD loc;
- {
- PSEGMENT ps = HashFind (loc);
- unless (ps == NULL)
- {
- HashRemove (ps);
- ps->location = 0;
- /*trace("Discard %s@%d\n", (LPSTR) ps->module->name, ps->ordinal);*/
- }
- }
-
- PSEGMENT FindSegment (ModName, Ordinal, Instance, Type)
- LPSTR ModName;
- WORD Ordinal, Instance;
- WORD Type;
- {
- PMODULE pm = LookupModule (ModName);
- PSEGMENT *pps;
- if (pm == NULL) return NULL;
- pps = &pm->pseg;
- while (*pps != NULL)
- {
- if ((*pps)->ordinal == Ordinal && (*pps)->instance == Instance)
- {
- /*trace("Found segment %s\n", (LPSTR) ModName);*/
- return *pps;
- }
- pps = &(*pps)->next;
- }
- if (FreeSeg < ARRAY_END(segs))
- {
- /*trace("New segment %s\n", (LPSTR) ModName);*/
- *pps = FreeSeg;
- FreeSeg->ordinal = Ordinal;
- FreeSeg->instance = Instance;
- FreeSeg->type = Type;
- FreeSeg->module = pm;
- FreeSeg->location = 0;
- FreeSeg->Procs = NULL;
- FreeSeg->hitcount = 0;
- return FreeSeg++;
- }
- return NULL;
- }
-
- void HashRemove (s)
- PSEGMENT s;
- {
- WORD index = s->location % MAXHASHVAL;
- WORD nxt;
- if (s->location == 0) return;
- until (hashtable[index] == s)
- {
- if (hashtable[index] == UNUSED) return; /* Not found */
- NextHash (index);
- }
- hashtable[index] = DELETED;
- if (hashtable[(index+1) % MAXHASHVAL] == UNUSED)
- {
- while (hashtable[index] == DELETED)
- {
- hashtable[index] = UNUSED;
- index = (index+MAXHASHVAL-1) % MAXHASHVAL;
- }
- }
- }
-
- void HashInsert (s)
- PSEGMENT s;
- {
- WORD index = s->location % MAXHASHVAL;
- if (s->location == 0) return;
-
- until (hashtable[index] == s || hashtable[index] == UNUSED || hashtable[index] == DELETED)
- {
- NextHash(index);
- }
- hashtable[index] = s;
- }
-
- PSEGMENT HashFind (w)
- WORD w;
- {
- WORD index = w % MAXHASHVAL;
- until (hashtable[index] == UNUSED)
- {
- if (hashtable[index] != DELETED && hashtable[index]->location == w)
- {
- return hashtable[index];
- }
- NextHash(index);
- }
- return NULL;
- }
-
- #define RATIO(x) { ratio = (unsigned long) (x) * 10000L / totalhits; rathi = (WORD) ratio/100; ratlo = (WORD) ratio%100; }
-
- void PrintSegments()
- {
- unsigned long ratio;
- WORD rathi, ratlo;
- PSEGMENT seg;
- FILE *outf = stderr;
- BOOL DoProcs = FALSE;
-
- if (OutputFileName != NULL)
- {
- outf = fopen(OutputFileName, "w");
- if (outf == NULL)
- {
- BadFile = OutputFileName;
- exc_raise (OP_FAILED);
- }
- }
-
- fprintf(outf, "Microsoft windows statistics\nSample interval %dms\nTotal hits %ld\n", TimerPeriod, totalhits);
- fprintf(outf, "\nSegments\n");
- for (seg = &segs[0]; seg < FreeSeg; seg++) if (seg->hitcount != 0)
- {
- WORD flag = seg->Procs != NULL && seg->hitcount != 0;
- if (seg->Procs != 0) DoProcs = TRUE;
- RATIO (seg->hitcount);
- fprintf(outf, "%2u.%02u%% %5u ", rathi, ratlo, seg->hitcount);
-
- if (seg->Procs != 0)
- fprintf(outf, "%s!%s\n", seg->module->name, seg->Procs->segname->s);
- else if (seg->type > 1)
- fprintf(outf, "%s@%04x\n", seg->module->name, seg->type);
- else
- fprintf(outf, "%s!%s:%u\n", seg->module->name, (seg->type == 0 ? "Code":"Data"), seg->ordinal+1);
- }
- if (otherhits != 0)
- {
- RATIO (otherhits);
- fprintf(outf, "%2u.%02u%% %5u Others\n", rathi, ratlo, otherhits);
- }
-
- if (DoProcs)
- {
- fprintf(outf, "\nProcedures\n");
- for (seg = &segs[0]; seg < FreeSeg; seg++) if (seg->hitcount != 0 && seg->Procs != 0)
- {
- WORD i;
- WORD n = seg->Procs->len;
- for (i = 0; i < n; i++) if (seg->Procs->vals[i].count != 0)
- {
- PNSTR sym = FindSymbol (seg->Procs->filename, seg->ordinal+1, seg->Procs->vals[i].label);
- if (sym == NULL)
- {
- BadFile = seg->Procs->filename;
- exc_raise(BAD_SYMBOL);
- }
- else
- {
- RATIO(seg->Procs->vals[i].count);
- fprintf(outf, "%2u.%02u%% %5u %s!%s:%s\n", rathi, ratlo,
- seg->Procs->vals[i].count,
- seg->module->name, seg->Procs->segname->s, sym->s);
- free((char *) sym);
- }
- }
- }
- }
- }
-
- /*
- * This procedure allows the stats to be reset at run-time by a multiplex interrupt.
- */
- void far ClearSegments()
- {
- PSEGMENT seg;
-
- for (seg = &segs[0]; seg < FreeSeg; seg++) if (seg->hitcount != 0)
- {
- seg->hitcount = 0;
- if (seg->Procs != NULL)
- {
- WORD i;
- WORD n = seg->Procs->len;
- for (i = 0; i < n; i++)
- seg->Procs->vals[i].count = 0;
- seg->Procs = NULL;
- }
- }
- totalhits = otherhits = 0;
- }
-